#!usr/bin/env python3
from xml.parsers.expat import ParserCreate
from collections import namedtuple
import os,time

#解析XML
   
class XmlElement(object):      
    def __init__(self,attr,char,name="",preNode=None):
        self.attr = attr
        self.char = char
        self.name = name
        self.preNode = preNode #根节类型
        self._children = []            
    def addChild(self,xmlEle):       
        if xmlEle in self._children:
            #msg = self.name+"重复添加"+xmlEle.name
            #print(msg)
            return
            #raise Exception(msg)
        self._children.append(xmlEle)
    def __repr__(self):
        return "XmlElement<name=%s attrList:%s>"%(self.name,str(self.attr))
    @property
    def children(self):
    	return self._children
        
#解释xml的类
class DFSaxXmlParser(object):    
    def __init__(self,xml,isLog=True):
        self._xmlData = dict()
        self._xml = xml
        self._curNode=''                
        self._curIndex = -1
        self._end = dict()
        self._curLine = None
        self._tree = dict()
        self._rootName = ""
        self.rootNode = None
        self._secName = ""
        self._isLog = isLog
        self.counter = 0
        self.parse(self._xml)        

    def parse(self,xml):
        p = ParserCreate()
        p.StartElementHandler = self.start_element
        p.EndElementHandler = self.end_element
        p.CharacterDataHandler = self.char_data
        self._p = p
        p.Parse(xml)
               
        
    def start_element(self,name,attrs):
        if self._isLog:
            print("--------------- start_element():name=",name,"attrs=",attrs,type(attrs))        
        if self._curNode!=name:        
            self._curNode = name
            self._curIndex = 0
        curNodes = self.getCurNodes()
        preNode = self.getPreNode()                        
        line = XmlElement(attrs,'',name,preNode)
        if preNode!=None and self._isLog:
            print("%%当前节点line.name=",line.name,line.attr,"上一个 preNode.name=",preNode.name,preNode.attr)
        curNodes.append(line)  
        self._curLine = line
        self._end[name] = False
        if self._rootName=="":
            self._rootName = name
            self.rootNode = line
        if self._secName=="" and self._rootName!="":
            self._secName = name
            
    def end_element(self,name):
        #print(" **** EEEEEEEE  end_element() name:",name,",_curLine.name=",self._curLine.name,'char=',self._curLine.char)
        self._end[name] = True
        #self.setChild(self._curLine)
        self.updateChildren(name)
        if self._rootName==name:
            print("XXX 循环次数=",self.counter)
    

    def char_data(self,text):              
        if self._curLine:
            self._curLine.char=self._curLine.char+text
            #print("char_data(): self._curLine.name=",self._curLine.name)
    def updateChildren(self,name):#更新所有子列表
        if self._rootName==name:
            #st = time.time()
            for key,nodes in self._xmlData.items():              
                for node in nodes:
                    if node.preNode!=None:
                        self.setChild(node)
            #et = time.time()
            #print("完成子列表更新 耗时:",round(et-st,3))
    def getCurNodes(self):
        if self._curNode in self._xmlData:
            curNodes = self._xmlData[self._curNode]
        else:
            curNodes = []
            self._xmlData[self._curNode] = curNodes;        
        return curNodes
    
    def getPreNode(self): #获取前一个节点,也就是父节点
        preNode = None
        if self._curLine != None:            
            preNode = self._curLine            
            while preNode!=None and self._end[preNode.name]:
                preNode = preNode.preNode
        return preNode
    
            
    def setChild(self,line):#追加一个子节点
        preNode = line.preNode 
        while preNode:            
            preNode.addChild(line)
            line = preNode
            preNode = line.preNode
            self.counter = self.counter+1            
   
    @property
    def xmlData(self):
        if not hasattr(self,"_xmlData"):
            self._xmlData = dict();
        return self._xmlData

    
    

    
    
    